*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
- * Copyright (c) 2012-2019, Even Rouault <even dot rouault at spatialys.com>
+ * Copyright (c) 2012-2024, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
******************************************************************************/
-#include "shapefil.h"
+#include "shapefil_private.h"
#include <math.h>
#include <stdbool.h>
#if defined(_MSC_VER)
#define STRCASECMP(a, b) (_stricmp(a, b))
-#elif defined(WIN32) || defined(_WIN32)
+#elif defined(_WIN32)
#define STRCASECMP(a, b) (stricmp(a, b))
#else
#include <strings.h>
#if _MSC_VER < 1900
#define snprintf _snprintf
#endif
-#elif defined(WIN32) || defined(_WIN32)
+#elif defined(_WIN32)
#ifndef snprintf
#define snprintf _snprintf
#endif
#define CPL_IGNORE_RET_VAL_INT(x) x
#endif
-#ifdef __cplusplus
-#define STATIC_CAST(type, x) static_cast<type>(x)
-#define REINTERPRET_CAST(type, x) reinterpret_cast<type>(x)
-#define CONST_CAST(type, x) const_cast<type>(x)
-#define SHPLIB_NULLPTR nullptr
-#else
-#define STATIC_CAST(type, x) ((type)(x))
-#define REINTERPRET_CAST(type, x) ((type)(x))
-#define CONST_CAST(type, x) ((type)(x))
-#define SHPLIB_NULLPTR NULL
-#endif
-
/************************************************************************/
/* DBFWriteHeader() */
/* */
/************************************************************************/
DBFHandle SHPAPI_CALL DBFOpen(const char *pszFilename, const char *pszAccess)
-
{
SAHooks sHooks;
for (int iField = 0; iField < nFields; iField++)
{
- unsigned char *pabyFInfo = pabyBuf + iField * XBASE_FLDHDR_SZ;
+ const unsigned char *pabyFInfo = pabyBuf + iField * XBASE_FLDHDR_SZ;
if (pabyFInfo[0] == HEADER_RECORD_TERMINATOR)
{
psDBF->nFields = iField;
const char SHPAPI_CALL1(*)
DBFReadStringAttribute(DBFHandle psDBF, int iRecord, int iField)
-
{
return STATIC_CAST(const char *,
DBFReadAttribute(psDBF, iRecord, iField, 'C'));
const char SHPAPI_CALL1(*)
DBFReadLogicalAttribute(DBFHandle psDBF, int iRecord, int iField)
-
{
return STATIC_CAST(const char *,
DBFReadAttribute(psDBF, iRecord, iField, 'L'));
}
+/************************************************************************/
+/* DBFReadDateAttribute() */
+/* */
+/* Read a date attribute. */
+/************************************************************************/
+
+SHPDate SHPAPI_CALL DBFReadDateAttribute(DBFHandle psDBF, int iRecord,
+ int iField)
+{
+ const char *pdateValue = STATIC_CAST(
+ const char *, DBFReadAttribute(psDBF, iRecord, iField, 'D'));
+
+ SHPDate date;
+
+ if (pdateValue == SHPLIB_NULLPTR)
+ {
+ date.year = 0;
+ date.month = 0;
+ date.day = 0;
+ }
+ else if (3 != sscanf(pdateValue, "%4d%2d%2d", &date.year, &date.month,
+ &date.day))
+ {
+ date.year = 0;
+ date.month = 0;
+ date.day = 0;
+ }
+
+ return date;
+}
+
/************************************************************************/
/* DBFIsValueNULL() */
/* */
/* Return TRUE if the passed string is NULL. */
/************************************************************************/
-static bool DBFIsValueNULL(char chType, const char *pszValue)
+static bool DBFIsValueNULL(char chType, const char *pszValue, int size)
{
if (pszValue == SHPLIB_NULLPTR)
return true;
return true;
case 'D':
- /* NULL date fields have value "00000000" */
+ {
+ const char DIGIT_ZERO = '0';
+ /* NULL date fields have value "00000000" or "0"*size */
/* Some DBF files have fields filled with spaces */
/* (trimmed by DBFReadStringAttribute) to indicate null */
/* values for dates (#4265). */
/* And others have ' 0': https://lists.osgeo.org/pipermail/gdal-dev/2023-November/058010.html */
- return strncmp(pszValue, "00000000", 8) == 0 ||
- strcmp(pszValue, " ") == 0 || strcmp(pszValue, "0") == 0;
+ /* And others just empty string: https://github.com/OSGeo/gdal/issues/10405 */
+ if (pszValue[0] == 0 || strncmp(pszValue, "00000000", 8) == 0 ||
+ strcmp(pszValue, " ") == 0 || strcmp(pszValue, "0") == 0)
+ return true;
+ for (int i = 0; i < size; i++)
+ if (pszValue[i] != DIGIT_ZERO)
+ return false;
+ return true;
+ }
case 'L':
/* NULL boolean fields have value "?" */
/* Contributed by Jim Matthews. */
/************************************************************************/
-int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle psDBF, int iRecord, int iField)
+int SHPAPI_CALL DBFIsAttributeNULL(const DBFHandle psDBF, int iRecord,
+ int iField)
{
const char *pszValue = DBFReadStringAttribute(psDBF, iRecord, iField);
if (pszValue == SHPLIB_NULLPTR)
return TRUE;
- return DBFIsValueNULL(psDBF->pachFieldType[iField], pszValue);
+ return DBFIsValueNULL(psDBF->pachFieldType[iField], pszValue,
+ psDBF->panFieldSize[iField]);
}
/************************************************************************/
/* Return the number of fields in this table. */
/************************************************************************/
-int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF)
-
+int SHPAPI_CALL DBFGetFieldCount(const DBFHandle psDBF)
{
return (psDBF->nFields);
}
/* Return the number of records in this table. */
/************************************************************************/
-int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF)
-
+int SHPAPI_CALL DBFGetRecordCount(const DBFHandle psDBF)
{
return (psDBF->nRecords);
}
/* bytes long. */
/************************************************************************/
-DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField,
+DBFFieldType SHPAPI_CALL DBFGetFieldInfo(const DBFHandle psDBF, int iField,
char *pszFieldName, int *pnWidth,
int *pnDecimals)
-
{
if (iField < 0 || iField >= psDBF->nFields)
return (FTInvalid);
if (psDBF->panFieldSize[iField] >= 1 &&
(*STATIC_CAST(char *, pValue) == 'F' ||
*STATIC_CAST(char *, pValue) == 'T'))
+ {
*(pabyRec + psDBF->panFieldOffset[iField]) =
*STATIC_CAST(char *, pValue);
+ }
+ else
+ {
+ nRetResult = false;
+ }
break;
default:
/* Assign all the record fields. */
/* -------------------------------------------------------------------- */
int j;
- if (STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue))) >
+ if (STATIC_CAST(int, strlen(STATIC_CAST(const char *, pValue))) >
psDBF->panFieldSize[iField])
j = psDBF->panFieldSize[iField];
else
{
memset(pabyRec + psDBF->panFieldOffset[iField], ' ',
psDBF->panFieldSize[iField]);
- j = STATIC_CAST(int, strlen(STATIC_CAST(char *, pValue)));
+ j = STATIC_CAST(int, strlen(STATIC_CAST(const char *, pValue)));
}
- strncpy(
+ memcpy(
REINTERPRET_CAST(char *, pabyRec + psDBF->panFieldOffset[iField]),
STATIC_CAST(const char *, pValue), j);
}
/************************************************************************/
/* DBFWriteIntegerAttribute() */
/* */
-/* Write a integer attribute. */
+/* Write an integer attribute. */
/************************************************************************/
int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle psDBF, int iRecord,
int SHPAPI_CALL DBFWriteStringAttribute(DBFHandle psDBF, int iRecord,
int iField, const char *pszValue)
-
{
return (
DBFWriteAttribute(psDBF, iRecord, iField,
/************************************************************************/
/* DBFWriteNULLAttribute() */
/* */
-/* Write a string attribute. */
+/* Write a NULL attribute. */
/************************************************************************/
int SHPAPI_CALL DBFWriteNULLAttribute(DBFHandle psDBF, int iRecord, int iField)
-
{
return (DBFWriteAttribute(psDBF, iRecord, iField, SHPLIB_NULLPTR));
}
int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle psDBF, int iRecord,
int iField, const char lValue)
-
{
return (
DBFWriteAttribute(psDBF, iRecord, iField,
STATIC_CAST(void *, CONST_CAST(char *, &lValue))));
}
+/************************************************************************/
+/* DBFWriteDateAttribute() */
+/* */
+/* Write a date attribute. */
+/************************************************************************/
+
+int SHPAPI_CALL DBFWriteDateAttribute(DBFHandle psDBF, int iRecord, int iField,
+ const SHPDate *lValue)
+{
+ if (SHPLIB_NULLPTR == lValue)
+ return false;
+ /* check for supported digit range, but do not check for valid date */
+ if (lValue->year < 0 || lValue->year > 9999)
+ return false;
+ if (lValue->month < 0 || lValue->month > 99)
+ return false;
+ if (lValue->day < 0 || lValue->day > 99)
+ return false;
+ char dateValue[9]; /* "yyyyMMdd\0" */
+ snprintf(dateValue, sizeof(dateValue), "%04d%02d%02d", lValue->year,
+ lValue->month, lValue->day);
+ return (DBFWriteAttributeDirectly(psDBF, iRecord, iField, dateValue));
+}
+
/************************************************************************/
/* DBFWriteTuple() */
/* */
/************************************************************************/
const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity)
-
{
if (hEntity < 0 || hEntity >= psDBF->nRecords)
return SHPLIB_NULLPTR;
/************************************************************************/
/* DBFCloneEmpty() */
/* */
-/* Read one of the attribute fields of a record. */
+/* Create a new .dbf file with same code page and field */
+/* definitions as the given handle. */
/************************************************************************/
-DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF, const char *pszFilename)
+DBFHandle SHPAPI_CALL DBFCloneEmpty(const DBFHandle psDBF,
+ const char *pszFilename)
{
- DBFHandle newDBF = DBFCreateEx(pszFilename, psDBF->pszCodePage);
+ DBFHandle newDBF =
+ DBFCreateLL(pszFilename, psDBF->pszCodePage, &psDBF->sHooks);
if (newDBF == SHPLIB_NULLPTR)
return SHPLIB_NULLPTR;
/* 'M' (Memo: 10 digits .DBT block ptr) */
/************************************************************************/
-char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle psDBF, int iField)
-
+char SHPAPI_CALL DBFGetNativeFieldType(const DBFHandle psDBF, int iField)
{
if (iField >= 0 && iField < psDBF->nFields)
return psDBF->pachFieldType[iField];
/* Contributed by Jim Matthews. */
/************************************************************************/
-int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
+int SHPAPI_CALL DBFGetFieldIndex(const DBFHandle psDBF,
+ const char *pszFieldName)
{
char name[XBASE_FLDNAME_LEN_READ + 1];
/* it returns FALSE. */
/************************************************************************/
-int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape)
+int SHPAPI_CALL DBFIsRecordDeleted(const DBFHandle psDBF, int iShape)
{
/* -------------------------------------------------------------------- */
/* Verify selection. */
/* DBFGetCodePage */
/************************************************************************/
-const char SHPAPI_CALL1(*) DBFGetCodePage(DBFHandle psDBF)
+const char SHPAPI_CALL1(*) DBFGetCodePage(const DBFHandle psDBF)
{
if (psDBF == SHPLIB_NULLPTR)
return SHPLIB_NULLPTR;
/* a simple malloc() would be enough, but calloc() helps clang static
* analyzer */
int *panFieldOffsetNew =
- STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+ STATIC_CAST(int *, calloc(psDBF->nFields, sizeof(int)));
int *panFieldSizeNew =
- STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+ STATIC_CAST(int *, calloc(psDBF->nFields, sizeof(int)));
int *panFieldDecimalsNew =
- STATIC_CAST(int *, calloc(sizeof(int), psDBF->nFields));
+ STATIC_CAST(int *, calloc(psDBF->nFields, sizeof(int)));
char *pachFieldTypeNew =
- STATIC_CAST(char *, calloc(sizeof(char), psDBF->nFields));
+ STATIC_CAST(char *, calloc(psDBF->nFields, sizeof(char)));
char *pszHeaderNew = STATIC_CAST(
char *, malloc(sizeof(char) * XBASE_FLDHDR_SZ * psDBF->nFields));
char *pszOldField =
STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
- /* cppcheck-suppress uninitdata */
pszOldField[nOldWidth] = 0;
/* move records to their new positions */
}
memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
- const bool bIsNULL = DBFIsValueNULL(chOldType, pszOldField);
+ const bool bIsNULL =
+ DBFIsValueNULL(chOldType, pszOldField, nOldWidth);
if (nWidth != nOldWidth)
{
char *pszOldField =
STATIC_CAST(char *, malloc(sizeof(char) * (nOldWidth + 1)));
- /* cppcheck-suppress uninitdata */
pszOldField[nOldWidth] = 0;
/* move records to their new positions */
}
memcpy(pszOldField, pszRecord + nOffset, nOldWidth);
- const bool bIsNULL = DBFIsValueNULL(chOldType, pszOldField);
+ const bool bIsNULL =
+ DBFIsValueNULL(chOldType, pszOldField, nOldWidth);
if (nOffset + nOldWidth < nOldRecordLength)
{
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
- * Copyright (c) 2012-2016, Even Rouault <even dot rouault at spatialys.com>
+ * Copyright (c) 2012-2024, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
******************************************************************************
{
#endif
-/************************************************************************/
-/* Version related macros (added in 1.6.0) */
-/************************************************************************/
+ /************************************************************************/
+ /* Version related macros (added in 1.6.0) */
+ /************************************************************************/
#define SHAPELIB_VERSION_MAJOR 1
#define SHAPELIB_VERSION_MINOR 6
-#define SHAPELIB_VERSION_MICRO 0
+#define SHAPELIB_VERSION_MICRO 1
-#define SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro) \
+#define SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro) \
((major) * 10000 + (minor) * 100 + (micro))
-#define SHAPELIB_VERSION_NUMBER \
- SHAPELIB_MAKE_VERSION_NUMBER(SHAPELIB_VERSION_MAJOR, SHAPELIB_VERSION_MINOR, SHAPELIB_VERSION_MICRO)
+#define SHAPELIB_VERSION_NUMBER \
+ SHAPELIB_MAKE_VERSION_NUMBER(SHAPELIB_VERSION_MAJOR, \
+ SHAPELIB_VERSION_MINOR, \
+ SHAPELIB_VERSION_MICRO)
-#define SHAPELIB_AT_LEAST(major, minor, micro) \
- (SHAPELIB_VERSION_NUMBER >= SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro))
+#define SHAPELIB_AT_LEAST(major, minor, micro) \
+ (SHAPELIB_VERSION_NUMBER >= \
+ SHAPELIB_MAKE_VERSION_NUMBER(major, minor, micro))
/************************************************************************/
/* Configuration options. */
/* On some platforms, additional file IO hooks are defined that */
/* UTF-8 encoded filenames Unicode filenames */
/* -------------------------------------------------------------------- */
-#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#if defined(_WIN32)
#define SHPAPI_WINDOWS
#define SHPAPI_UTF8_HOOKS
#endif
typedef SHPInfo *SHPHandle;
+ typedef struct
+ {
+ int year;
+ int month;
+ int day;
+ } SHPDate;
+
/* -------------------------------------------------------------------- */
/* Shape types (nSHPType) */
/* -------------------------------------------------------------------- */
#define SHPP_RING 5
/* -------------------------------------------------------------------- */
- /* SHPObject - represents on shape (without attributes) read */
+ /* SHPObject - represents one shape (without attributes) read */
/* from the .shp file. */
/* -------------------------------------------------------------------- */
struct tagSHPObject
SHPHandle SHPAPI_CALL SHPCreate(const char *pszShapeFile, int nShapeType);
SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszShapeFile, int nShapeType,
const SAHooks *psHooks);
- void SHPAPI_CALL SHPGetInfo(SHPHandle hSHP, int *pnEntities,
+ void SHPAPI_CALL SHPGetInfo(const SHPHandle hSHP, int *pnEntities,
int *pnShapeType, double *padfMinBound,
double *padfMaxBound);
- SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle hSHP, int iShape);
+ SHPObject SHPAPI_CALL1(*) SHPReadObject(const SHPHandle hSHP, int iShape);
int SHPAPI_CALL SHPWriteObject(SHPHandle hSHP, int iShape,
- SHPObject *psObject);
+ const SHPObject *psObject);
void SHPAPI_CALL SHPDestroyObject(SHPObject *psObject);
void SHPAPI_CALL SHPComputeExtents(SHPObject *psObject);
SHPCreateSimpleObject(int nSHPType, int nVertices, const double *padfX,
const double *padfY, const double *padfZ);
- int SHPAPI_CALL SHPRewindObject(SHPHandle hSHP, SHPObject *psObject);
+ int SHPAPI_CALL SHPRewindObject(const SHPHandle hSHP, SHPObject *psObject);
void SHPAPI_CALL SHPClose(SHPHandle hSHP);
void SHPAPI_CALL SHPWriteHeader(SHPHandle hSHP);
int SHPAPI_CALL SHPWriteTree(SHPTree *hTree, const char *pszFilename);
int SHPAPI_CALL SHPTreeAddShapeId(SHPTree *hTree, SHPObject *psObject);
- int SHPAPI_CALL SHPTreeRemoveShapeId(SHPTree *hTree, int nShapeId);
void SHPAPI_CALL SHPTreeTrimExtraNodes(SHPTree *hTree);
int SHPAPI_CALL1(*)
- SHPTreeFindLikelyShapes(SHPTree *hTree, double *padfBoundsMin,
+ SHPTreeFindLikelyShapes(const SHPTree *hTree, double *padfBoundsMin,
double *padfBoundsMax, int *);
int SHPAPI_CALL SHPCheckBoundsOverlap(const double *, const double *,
const double *, const double *, int);
void SHPAPI_CALL SHPCloseDiskTree(SHPTreeDiskHandle hDiskTree);
int SHPAPI_CALL1(*)
- SHPSearchDiskTreeEx(SHPTreeDiskHandle hDiskTree, double *padfBoundsMin,
- double *padfBoundsMax, int *pnShapeCount);
+ SHPSearchDiskTreeEx(const SHPTreeDiskHandle hDiskTree,
+ double *padfBoundsMin, double *padfBoundsMax,
+ int *pnShapeCount);
int SHPAPI_CALL SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename,
const SAHooks *psHooks);
void SHPAPI_CALL SBNCloseDiskTree(SBNSearchHandle hSBN);
int SHPAPI_CALL1(*)
- SBNSearchDiskTree(SBNSearchHandle hSBN, const double *padfBoundsMin,
+ SBNSearchDiskTree(const SBNSearchHandle hSBN,
+ const double *padfBoundsMin,
const double *padfBoundsMax, int *pnShapeCount);
int SHPAPI_CALL1(*)
- SBNSearchDiskTreeInteger(SBNSearchHandle hSBN, int bMinX, int bMinY,
- int bMaxX, int bMaxY, int *pnShapeCount);
+ SBNSearchDiskTreeInteger(const SBNSearchHandle hSBN, int bMinX,
+ int bMinY, int bMaxX, int bMaxY,
+ int *pnShapeCount);
void SHPAPI_CALL SBNSearchFreeIds(int *panShapeId);
const char *pszCodePage,
const SAHooks *psHooks);
- int SHPAPI_CALL DBFGetFieldCount(DBFHandle psDBF);
- int SHPAPI_CALL DBFGetRecordCount(DBFHandle psDBF);
+ int SHPAPI_CALL DBFGetFieldCount(const DBFHandle psDBF);
+ int SHPAPI_CALL DBFGetRecordCount(const DBFHandle psDBF);
int SHPAPI_CALL DBFAddField(DBFHandle hDBF, const char *pszFieldName,
DBFFieldType eType, int nWidth, int nDecimals);
const char *pszFieldName, char chType,
int nWidth, int nDecimals);
- DBFFieldType SHPAPI_CALL DBFGetFieldInfo(DBFHandle psDBF, int iField,
+ DBFFieldType SHPAPI_CALL DBFGetFieldInfo(const DBFHandle psDBF, int iField,
char *pszFieldName, int *pnWidth,
int *pnDecimals);
- int SHPAPI_CALL DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
+ int SHPAPI_CALL DBFGetFieldIndex(const DBFHandle psDBF,
+ const char *pszFieldName);
int SHPAPI_CALL DBFReadIntegerAttribute(DBFHandle hDBF, int iShape,
int iField);
DBFReadStringAttribute(DBFHandle hDBF, int iShape, int iField);
const char SHPAPI_CALL1(*)
DBFReadLogicalAttribute(DBFHandle hDBF, int iShape, int iField);
- int SHPAPI_CALL DBFIsAttributeNULL(DBFHandle hDBF, int iShape, int iField);
+ SHPDate SHPAPI_CALL DBFReadDateAttribute(DBFHandle hDBF, int iShape,
+ int iField);
+ int SHPAPI_CALL DBFIsAttributeNULL(const DBFHandle hDBF, int iShape,
+ int iField);
int SHPAPI_CALL DBFWriteIntegerAttribute(DBFHandle hDBF, int iShape,
int iField, int nFieldValue);
int SHPAPI_CALL DBFWriteLogicalAttribute(DBFHandle hDBF, int iShape,
int iField,
const char lFieldValue);
+ int SHPAPI_CALL DBFWriteDateAttribute(DBFHandle hDBF, int iShape,
+ int iField,
+ const SHPDate *dateFieldValue);
int SHPAPI_CALL DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity,
int iField, const void *pValue);
const char SHPAPI_CALL1(*) DBFReadTuple(DBFHandle psDBF, int hEntity);
int SHPAPI_CALL DBFWriteTuple(DBFHandle psDBF, int hEntity,
const void *pRawTuple);
- int SHPAPI_CALL DBFIsRecordDeleted(DBFHandle psDBF, int iShape);
+ int SHPAPI_CALL DBFIsRecordDeleted(const DBFHandle psDBF, int iShape);
int SHPAPI_CALL DBFMarkRecordDeleted(DBFHandle psDBF, int iShape,
int bIsDeleted);
- DBFHandle SHPAPI_CALL DBFCloneEmpty(DBFHandle psDBF,
+ DBFHandle SHPAPI_CALL DBFCloneEmpty(const DBFHandle psDBF,
const char *pszFilename);
void SHPAPI_CALL DBFClose(DBFHandle hDBF);
void SHPAPI_CALL DBFUpdateHeader(DBFHandle hDBF);
- char SHPAPI_CALL DBFGetNativeFieldType(DBFHandle hDBF, int iField);
+ char SHPAPI_CALL DBFGetNativeFieldType(const DBFHandle hDBF, int iField);
- const char SHPAPI_CALL1(*) DBFGetCodePage(DBFHandle psDBF);
+ const char SHPAPI_CALL1(*) DBFGetCodePage(const DBFHandle psDBF);
void SHPAPI_CALL DBFSetLastModifiedDate(DBFHandle psDBF, int nYYSince1900,
int nMM, int nDD);
*
******************************************************************************
* Copyright (c) 1999, 2001, Frank Warmerdam
- * Copyright (c) 2011-2019, Even Rouault <even dot rouault at spatialys.com>
+ * Copyright (c) 2011-2024, Even Rouault <even dot rouault at spatialys.com>
*
* SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
******************************************************************************/
-#include "shapefil.h"
+#include "shapefil_private.h"
#include <assert.h>
#include <errno.h>
#if _MSC_VER < 1900
#define snprintf _snprintf
#endif
-#elif defined(WIN32) || defined(_WIN32)
+#elif defined(_WIN32)
#ifndef snprintf
#define snprintf _snprintf
#endif
#endif
#endif
-#ifndef CPL_UNUSED
-#if defined(__GNUC__) && __GNUC__ >= 4
-#define CPL_UNUSED __attribute((__unused__))
-#else
-#define CPL_UNUSED
-#endif
-#endif
-
-#ifndef bBigEndian
-#if defined(CPL_LSB)
-#define bBigEndian false
-#elif defined(CPL_MSB)
-#define bBigEndian true
-#else
-#ifndef static_var_bBigEndian_defined
-#define static_var_bBigEndian_defined
-static bool bBigEndian = false;
-#endif
-#endif
-#endif
-
-#ifdef __cplusplus
-#define STATIC_CAST(type, x) static_cast<type>(x)
-#define SHPLIB_NULLPTR nullptr
-#else
-#define STATIC_CAST(type, x) ((type)(x))
-#define SHPLIB_NULLPTR NULL
-#endif
-
-/************************************************************************/
-/* SwapWord() */
-/* */
-/* Swap a 2, 4 or 8 byte word. */
-/************************************************************************/
-
-#ifndef SwapWord_defined
-#define SwapWord_defined
-static void SwapWord(int length, void *wordP)
-{
- for (int i = 0; i < length / 2; i++)
- {
- const unsigned char temp = STATIC_CAST(unsigned char *, wordP)[i];
- STATIC_CAST(unsigned char *, wordP)
- [i] = STATIC_CAST(unsigned char *, wordP)[length - i - 1];
- STATIC_CAST(unsigned char *, wordP)[length - i - 1] = temp;
- }
-}
+/* Allows customization of the message in vendored builds (such as GDAL) */
+#ifndef SHP_RESTORE_SHX_HINT_MESSAGE
+#define SHP_RESTORE_SHX_HINT_MESSAGE \
+ " Use SHPRestoreSHX() to restore or create it."
#endif
/************************************************************************/
uint32_t i32 = psSHP->nFileSize / 2; /* file size */
ByteCopy(&i32, abyHeader + 24, 4);
- if (!bBigEndian)
- SwapWord(4, abyHeader + 24);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(abyHeader + 24);
+#endif
i32 = 1000; /* version */
ByteCopy(&i32, abyHeader + 28, 4);
- if (bBigEndian)
- SwapWord(4, abyHeader + 28);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(abyHeader + 28);
+#endif
i32 = psSHP->nShapeType; /* shape type */
ByteCopy(&i32, abyHeader + 32, 4);
- if (bBigEndian)
- SwapWord(4, abyHeader + 32);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(abyHeader + 32);
+#endif
double dValue = psSHP->adBoundsMin[0]; /* set bounds */
ByteCopy(&dValue, abyHeader + 36, 8);
- if (bBigEndian)
- SwapWord(8, abyHeader + 36);
-
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(abyHeader + 36);
+#endif
dValue = psSHP->adBoundsMin[1];
ByteCopy(&dValue, abyHeader + 44, 8);
- if (bBigEndian)
- SwapWord(8, abyHeader + 44);
-
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(abyHeader + 44);
+#endif
dValue = psSHP->adBoundsMax[0];
ByteCopy(&dValue, abyHeader + 52, 8);
- if (bBigEndian)
- SwapWord(8, abyHeader + 52);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(abyHeader + 52);
+#endif
dValue = psSHP->adBoundsMax[1];
ByteCopy(&dValue, abyHeader + 60, 8);
- if (bBigEndian)
- SwapWord(8, abyHeader + 60);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(abyHeader + 60);
+#endif
dValue = psSHP->adBoundsMin[2]; /* z */
ByteCopy(&dValue, abyHeader + 68, 8);
- if (bBigEndian)
- SwapWord(8, abyHeader + 68);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(abyHeader + 68);
+#endif
dValue = psSHP->adBoundsMax[2];
ByteCopy(&dValue, abyHeader + 76, 8);
- if (bBigEndian)
- SwapWord(8, abyHeader + 76);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(abyHeader + 76);
+#endif
dValue = psSHP->adBoundsMin[3]; /* m */
ByteCopy(&dValue, abyHeader + 84, 8);
- if (bBigEndian)
- SwapWord(8, abyHeader + 84);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(abyHeader + 84);
+#endif
dValue = psSHP->adBoundsMax[3];
ByteCopy(&dValue, abyHeader + 92, 8);
- if (bBigEndian)
- SwapWord(8, abyHeader + 92);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(abyHeader + 92);
+#endif
/* -------------------------------------------------------------------- */
/* Write .shp file header. */
/* -------------------------------------------------------------------- */
i32 = (psSHP->nRecords * 2 * sizeof(uint32_t) + 100) / 2; /* file size */
ByteCopy(&i32, abyHeader + 24, 4);
- if (!bBigEndian)
- SwapWord(4, abyHeader + 24);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(abyHeader + 24);
+#endif
if (psSHP->sHooks.FSeek(psSHP->fpSHX, 0, 0) != 0 ||
psSHP->sHooks.FWrite(abyHeader, 100, 1, psSHP->fpSHX) != 1)
{
panSHX[i * 2] = psSHP->panRecOffset[i] / 2;
panSHX[i * 2 + 1] = psSHP->panRecSize[i] / 2;
- if (!bBigEndian)
- SwapWord(4, panSHX + i * 2);
- if (!bBigEndian)
- SwapWord(4, panSHX + i * 2 + 1);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(panSHX + i * 2);
+ SHP_SWAP32(panSHX + i * 2 + 1);
+#endif
}
if (STATIC_CAST(int, psSHP->sHooks.FWrite(panSHX, sizeof(uint32_t) * 2,
pszAccess = "rb";
}
-/* -------------------------------------------------------------------- */
-/* Establish the byte order on this machine. */
-/* -------------------------------------------------------------------- */
-#if !defined(bBigEndian)
- {
- int i = 1;
- if (*((unsigned char *)&i) == 1)
- bBigEndian = false;
- else
- bBigEndian = true;
- }
-#endif
-
/* -------------------------------------------------------------------- */
/* Initialize the info structure. */
/* -------------------------------------------------------------------- */
- SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo), 1));
+ SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo)));
psSHP->bUpdated = FALSE;
memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
if (psSHP->fpSHX == SHPLIB_NULLPTR)
{
- const size_t nMessageLen = strlen(pszFullname) * 2 + 256;
+ const size_t nMessageLen =
+ 64 + strlen(pszFullname) * 2 + strlen(SHP_RESTORE_SHX_HINT_MESSAGE);
char *pszMessage = STATIC_CAST(char *, malloc(nMessageLen));
pszFullname[nLenWithoutExtension] = 0;
- snprintf(pszMessage, nMessageLen,
- "Unable to open %s.shx or %s.SHX. "
- "Set SHAPE_RESTORE_SHX config option to YES to restore or "
- "create it.",
- pszFullname, pszFullname);
+ snprintf(
+ pszMessage, nMessageLen,
+ "Unable to open %s.shx or %s.SHX." SHP_RESTORE_SHX_HINT_MESSAGE,
+ pszFullname, pszFullname);
psHooks->Error(pszMessage);
free(pszMessage);
/* -------------------------------------------------------------------- */
double dValue;
- if (bBigEndian)
- SwapWord(8, pabyBuf + 36);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyBuf + 36);
+#endif
memcpy(&dValue, pabyBuf + 36, 8);
psSHP->adBoundsMin[0] = dValue;
- if (bBigEndian)
- SwapWord(8, pabyBuf + 44);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyBuf + 44);
+#endif
memcpy(&dValue, pabyBuf + 44, 8);
psSHP->adBoundsMin[1] = dValue;
- if (bBigEndian)
- SwapWord(8, pabyBuf + 52);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyBuf + 52);
+#endif
memcpy(&dValue, pabyBuf + 52, 8);
psSHP->adBoundsMax[0] = dValue;
- if (bBigEndian)
- SwapWord(8, pabyBuf + 60);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyBuf + 60);
+#endif
memcpy(&dValue, pabyBuf + 60, 8);
psSHP->adBoundsMax[1] = dValue;
- if (bBigEndian)
- SwapWord(8, pabyBuf + 68); /* z */
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyBuf + 68); /* z */
+#endif
memcpy(&dValue, pabyBuf + 68, 8);
psSHP->adBoundsMin[2] = dValue;
- if (bBigEndian)
- SwapWord(8, pabyBuf + 76);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyBuf + 76);
+#endif
memcpy(&dValue, pabyBuf + 76, 8);
psSHP->adBoundsMax[2] = dValue;
- if (bBigEndian)
- SwapWord(8, pabyBuf + 84); /* z */
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyBuf + 84); /* z */
+#endif
memcpy(&dValue, pabyBuf + 84, 8);
psSHP->adBoundsMin[3] = dValue;
- if (bBigEndian)
- SwapWord(8, pabyBuf + 92);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyBuf + 92);
+#endif
memcpy(&dValue, pabyBuf + 92, 8);
psSHP->adBoundsMax[3] = dValue;
{
unsigned int nOffset;
memcpy(&nOffset, pabyBuf + i * 8, 4);
- if (!bBigEndian)
- SwapWord(4, &nOffset);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nOffset);
+#endif
unsigned int nLength;
memcpy(&nLength, pabyBuf + i * 8 + 4, 4);
- if (!bBigEndian)
- SwapWord(4, &nLength);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nLength);
+#endif
if (nOffset > STATIC_CAST(unsigned int, INT_MAX))
{
pszAccess = "rb";
}
-/* -------------------------------------------------------------------- */
-/* Establish the byte order on this machine. */
-/* -------------------------------------------------------------------- */
-#if !defined(bBigEndian)
- {
- int i = 1;
- if (*((unsigned char *)&i) == 1)
- bBigEndian = false;
- else
- bBigEndian = true;
- }
-#endif
-
/* -------------------------------------------------------------------- */
/* Open the .shp file. Note that files pulled from */
/* a PC to Unix with upper case filenames won't work! */
char abyReadRecord[8];
unsigned int nRecordOffsetBE = nRecordOffset;
- if (!bBigEndian)
- SwapWord(4, &nRecordOffsetBE);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nRecordOffsetBE);
+#endif
memcpy(abyReadRecord, &nRecordOffsetBE, 4);
memcpy(abyReadRecord + 4, &nRecordLength, 4);
- if (!bBigEndian)
- SwapWord(4, &nRecordLength);
-
- if (bBigEndian)
- SwapWord(4, &nSHPType);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nRecordLength);
+#endif
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nSHPType);
+#endif
// Sanity check on record length
if (nRecordLength < 1 ||
"Error parsing .shp to restore .shx. "
"Invalid record length = %u at record starting at "
"offset %u",
- nSHPType, nCurrentSHPOffset);
+ nRecordLength, nCurrentSHPOffset);
psHooks->Error(szErrorMsg);
nRetCode = FALSE;
}
nRealSHXContentSize /= 2; // Bytes counted -> WORDs
- if (!bBigEndian)
- SwapWord(4, &nRealSHXContentSize);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nRealSHXContentSize);
+#endif
+
psHooks->FSeek(fpSHX, 24, 0);
psHooks->FWrite(&nRealSHXContentSize, 4, 1, fpSHX);
/* Fetch general information about the shape file. */
/************************************************************************/
-void SHPAPI_CALL SHPGetInfo(SHPHandle psSHP, int *pnEntities, int *pnShapeType,
- double *padfMinBound, double *padfMaxBound)
+void SHPAPI_CALL SHPGetInfo(const SHPHandle psSHP, int *pnEntities,
+ int *pnShapeType, double *padfMinBound,
+ double *padfMaxBound)
{
if (psSHP == SHPLIB_NULLPTR)
return;
SHPHandle SHPAPI_CALL SHPCreateLL(const char *pszLayer, int nShapeType,
const SAHooks *psHooks)
{
-/* -------------------------------------------------------------------- */
-/* Establish the byte order on this system. */
-/* -------------------------------------------------------------------- */
-#if !defined(bBigEndian)
- {
- int i = 1;
- if (*((unsigned char *)&i) == 1)
- bBigEndian = false;
- else
- bBigEndian = true;
- }
-#endif
-
/* -------------------------------------------------------------------- */
/* Open the two files so we can write their headers. */
/* -------------------------------------------------------------------- */
psHooks->Error(szErrorMsg);
free(pszFullname);
- return NULL;
+ return SHPLIB_NULLPTR;
}
memcpy(pszFullname + nLenWithoutExtension, ".shx", 5);
free(pszFullname);
psHooks->FClose(fpSHP);
- return NULL;
+ return SHPLIB_NULLPTR;
}
free(pszFullname);
uint32_t i32 = 50; /* file size */
ByteCopy(&i32, abyHeader + 24, 4);
- if (!bBigEndian)
- SwapWord(4, abyHeader + 24);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(abyHeader + 24);
+#endif
i32 = 1000; /* version */
ByteCopy(&i32, abyHeader + 28, 4);
- if (bBigEndian)
- SwapWord(4, abyHeader + 28);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(abyHeader + 28);
+#endif
i32 = nShapeType; /* shape type */
ByteCopy(&i32, abyHeader + 32, 4);
- if (bBigEndian)
- SwapWord(4, abyHeader + 32);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(abyHeader + 32);
+#endif
double dValue = 0.0; /* set bounds */
ByteCopy(&dValue, abyHeader + 36, 8);
free(pszFullname);
psHooks->FClose(fpSHP);
psHooks->FClose(fpSHX);
- return NULL;
+ return SHPLIB_NULLPTR;
}
/* -------------------------------------------------------------------- */
/* -------------------------------------------------------------------- */
i32 = 50; /* file size */
ByteCopy(&i32, abyHeader + 24, 4);
- if (!bBigEndian)
- SwapWord(4, abyHeader + 24);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(abyHeader + 24);
+#endif
if (psHooks->FWrite(abyHeader, 100, 1, fpSHX) != 1)
{
free(pszFullname);
psHooks->FClose(fpSHP);
psHooks->FClose(fpSHX);
- return NULL;
+ return SHPLIB_NULLPTR;
}
- SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(sizeof(SHPInfo), 1));
+ SHPHandle psSHP = STATIC_CAST(SHPHandle, calloc(1, sizeof(SHPInfo)));
psSHP->bUpdated = FALSE;
memcpy(&(psSHP->sHooks), psHooks, sizeof(SAHooks));
ByteCopy(&(psShape->dfXMax), pabyRec + 16, 8);
ByteCopy(&(psShape->dfYMax), pabyRec + 24, 8);
- if (bBigEndian)
- {
- SwapWord(8, pabyRec + 0);
- SwapWord(8, pabyRec + 8);
- SwapWord(8, pabyRec + 16);
- SwapWord(8, pabyRec + 24);
- }
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + 0);
+ SHP_SWAP64(pabyRec + 8);
+ SHP_SWAP64(pabyRec + 16);
+ SHP_SWAP64(pabyRec + 24);
+#endif
}
/************************************************************************/
psObject->nParts = MAX(1, nParts);
psObject->panPartStart =
- STATIC_CAST(int *, calloc(sizeof(int), psObject->nParts));
+ STATIC_CAST(int *, calloc(psObject->nParts, sizeof(int)));
psObject->panPartType =
STATIC_CAST(int *, malloc(sizeof(int) * psObject->nParts));
psObject->panPartType[i] = SHPP_RING;
}
- if (psObject->panPartStart[0] != 0)
- psObject->panPartStart[0] = 0;
+ psObject->panPartStart[0] = 0;
}
/* -------------------------------------------------------------------- */
const size_t nSize = sizeof(double) * nVertices;
psObject->padfX =
STATIC_CAST(double *, padfX ? malloc(nSize)
- : calloc(sizeof(double), nVertices));
+ : calloc(nVertices, sizeof(double)));
psObject->padfY =
STATIC_CAST(double *, padfY ? malloc(nSize)
- : calloc(sizeof(double), nVertices));
+ : calloc(nVertices, sizeof(double)));
psObject->padfZ = STATIC_CAST(
double *,
- padfZ &&bHasZ ? malloc(nSize) : calloc(sizeof(double), nVertices));
+ padfZ &&bHasZ ? malloc(nSize) : calloc(nVertices, sizeof(double)));
psObject->padfM = STATIC_CAST(
double *,
- padfM &&bHasM ? malloc(nSize) : calloc(sizeof(double), nVertices));
+ padfM &&bHasM ? malloc(nSize) : calloc(nVertices, sizeof(double)));
if (padfX != SHPLIB_NULLPTR)
memcpy(psObject->padfX, padfX, nSize);
if (padfY != SHPLIB_NULLPTR)
/************************************************************************/
int SHPAPI_CALL SHPWriteObject(SHPHandle psSHP, int nShapeId,
- SHPObject *psObject)
+ const SHPObject *psObject)
{
psSHP->bUpdated = TRUE;
_SHPSetBounds(pabyRec + 12, psObject);
- if (bBigEndian)
- SwapWord(4, &nPoints);
- if (bBigEndian)
- SwapWord(4, &nParts);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nPoints);
+ SHP_SWAP32(&nParts);
+#endif
ByteCopy(&nPoints, pabyRec + 40 + 8, 4);
ByteCopy(&nParts, pabyRec + 36 + 8, 4);
4 * psObject->nParts);
for (int i = 0; i < psObject->nParts; i++)
{
- if (bBigEndian)
- SwapWord(4, pabyRec + 44 + 8 + 4 * i);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(pabyRec + 44 + 8 + 4 * i);
+#endif
nRecordSize += 4;
}
4 * psObject->nParts);
for (int i = 0; i < psObject->nParts; i++)
{
- if (bBigEndian)
- SwapWord(4, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(pabyRec + nRecordSize);
+#endif
nRecordSize += 4;
}
}
ByteCopy(psObject->padfX + i, pabyRec + nRecordSize, 8);
ByteCopy(psObject->padfY + i, pabyRec + nRecordSize + 8, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
-
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize + 8);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+ SHP_SWAP64(pabyRec + nRecordSize + 8);
+#endif
nRecordSize += 2 * 8;
}
psObject->nSHPType == SHPT_MULTIPATCH)
{
ByteCopy(&(psObject->dfZMin), pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
ByteCopy(&(psObject->dfZMax), pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
for (int i = 0; i < psObject->nVertices; i++)
{
ByteCopy(psObject->padfZ + i, pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
}
}
psObject->nSHPType == SHPT_ARCZ))
{
ByteCopy(&(psObject->dfMMin), pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
ByteCopy(&(psObject->dfMMax), pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
for (int i = 0; i < psObject->nVertices; i++)
{
ByteCopy(psObject->padfM + i, pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
}
}
_SHPSetBounds(pabyRec + 12, psObject);
- if (bBigEndian)
- SwapWord(4, &nPoints);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nPoints);
+#endif
ByteCopy(&nPoints, pabyRec + 44, 4);
for (int i = 0; i < psObject->nVertices; i++)
ByteCopy(psObject->padfX + i, pabyRec + 48 + i * 16, 8);
ByteCopy(psObject->padfY + i, pabyRec + 48 + i * 16 + 8, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + 48 + i * 16);
- if (bBigEndian)
- SwapWord(8, pabyRec + 48 + i * 16 + 8);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + 48 + i * 16);
+ SHP_SWAP64(pabyRec + 48 + i * 16 + 8);
+#endif
}
nRecordSize = 48 + 16 * psObject->nVertices;
if (psObject->nSHPType == SHPT_MULTIPOINTZ)
{
ByteCopy(&(psObject->dfZMin), pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
ByteCopy(&(psObject->dfZMax), pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
for (int i = 0; i < psObject->nVertices; i++)
{
ByteCopy(psObject->padfZ + i, pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
}
}
psObject->nSHPType == SHPT_MULTIPOINTM))
{
ByteCopy(&(psObject->dfMMin), pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
ByteCopy(&(psObject->dfMMax), pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
for (int i = 0; i < psObject->nVertices; i++)
{
ByteCopy(psObject->padfM + i, pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
}
}
ByteCopy(psObject->padfX, pabyRec + 12, 8);
ByteCopy(psObject->padfY, pabyRec + 20, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + 12);
- if (bBigEndian)
- SwapWord(8, pabyRec + 20);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + 12);
+ SHP_SWAP64(pabyRec + 20);
+#endif
nRecordSize = 28;
if (psObject->nSHPType == SHPT_POINTZ)
{
ByteCopy(psObject->padfZ, pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
}
psObject->nSHPType == SHPT_POINTM))
{
ByteCopy(psObject->padfM, pabyRec + nRecordSize, 8);
- if (bBigEndian)
- SwapWord(8, pabyRec + nRecordSize);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP64(pabyRec + nRecordSize);
+#endif
nRecordSize += 8;
}
}
/* -------------------------------------------------------------------- */
uint32_t i32 =
(nShapeId < 0) ? psSHP->nRecords + 1 : nShapeId + 1; /* record # */
- if (!bBigEndian)
- SwapWord(4, &i32);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&i32);
+#endif
ByteCopy(&i32, pabyRec, 4);
i32 = (nRecordSize - 8) / 2; /* record size */
- if (!bBigEndian)
- SwapWord(4, &i32);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&i32);
+#endif
ByteCopy(&i32, pabyRec + 4, 4);
i32 = psObject->nSHPType; /* shape type */
- if (bBigEndian)
- SwapWord(4, &i32);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&i32);
+#endif
ByteCopy(&i32, pabyRec + 8, 4);
/* -------------------------------------------------------------------- */
/* for one shape. */
/************************************************************************/
-SHPObject SHPAPI_CALL1(*) SHPReadObject(SHPHandle psSHP, int hEntity)
+SHPObject SHPAPI_CALL1(*) SHPReadObject(const SHPHandle psSHP, int hEntity)
{
/* -------------------------------------------------------------------- */
/* Validate the record/entity number. */
psSHP->sHooks.Error(str);
return SHPLIB_NULLPTR;
}
- if (!bBigEndian)
- SwapWord(4, &nOffset);
- if (!bBigEndian)
- SwapWord(4, &nLength);
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nOffset);
+ SHP_SWAP32(&nLength);
+#endif
if (nOffset > STATIC_CAST(unsigned int, INT_MAX))
{
/* Do a sanity check */
int nSHPContentLength;
memcpy(&nSHPContentLength, psSHP->pabyRec + 4, 4);
- if (!bBigEndian)
- SwapWord(4, &(nSHPContentLength));
+#if !defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&(nSHPContentLength));
+#endif
if (nSHPContentLength < 0 || nSHPContentLength > INT_MAX / 2 - 4 ||
2 * nSHPContentLength + 8 != nBytesRead)
{
int nSHPType;
memcpy(&nSHPType, psSHP->pabyRec + 8, 4);
- if (bBigEndian)
- SwapWord(4, &(nSHPType));
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&(nSHPType));
+#endif
/* -------------------------------------------------------------------- */
/* Allocate and minimally initialize the object. */
/* -------------------------------------------------------------------- */
/* Get the X/Y bounds. */
/* -------------------------------------------------------------------- */
- memcpy(&(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8);
- memcpy(&(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8);
- memcpy(&(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8);
- memcpy(&(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8);
-
- if (bBigEndian)
- SwapWord(8, &(psShape->dfXMin));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfYMin));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfXMax));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfYMax));
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(&psShape->dfXMin, psSHP->pabyRec + 8 + 4);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfYMin, psSHP->pabyRec + 8 + 12);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfXMax, psSHP->pabyRec + 8 + 20);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfYMax, psSHP->pabyRec + 8 + 28);
+#else
+ memcpy(&psShape->dfXMin, psSHP->pabyRec + 8 + 4, 8);
+ memcpy(&psShape->dfYMin, psSHP->pabyRec + 8 + 12, 8);
+ memcpy(&psShape->dfXMax, psSHP->pabyRec + 8 + 20, 8);
+ memcpy(&psShape->dfYMax, psSHP->pabyRec + 8 + 28, 8);
+#endif
/* -------------------------------------------------------------------- */
/* Extract part/point count, and build vertex and part arrays */
uint32_t nParts;
memcpy(&nParts, psSHP->pabyRec + 36 + 8, 4);
- if (bBigEndian)
- SwapWord(4, &nPoints);
- if (bBigEndian)
- SwapWord(4, &nParts);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nPoints);
+ SHP_SWAP32(&nParts);
+#endif
/* nPoints and nParts are unsigned */
if (/* nPoints < 0 || nParts < 0 || */
memcpy(psShape->panPartStart, psSHP->pabyRec + 44 + 8, 4 * nParts);
for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++)
{
- if (bBigEndian)
- SwapWord(4, psShape->panPartStart + i);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(psShape->panPartStart + i);
+#endif
/* We check that the offset is inside the vertex array */
if (psShape->panPartStart[i] < 0 ||
memcpy(psShape->panPartType, psSHP->pabyRec + nOffset, 4 * nParts);
for (int i = 0; STATIC_CAST(uint32_t, i) < nParts; i++)
{
- if (bBigEndian)
- SwapWord(4, psShape->panPartType + i);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(psShape->panPartType + i);
+#endif
}
nOffset += 4 * nParts;
/* -------------------------------------------------------------------- */
for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfX + i,
+ psSHP->pabyRec + nOffset + i * 16);
+ SHP_SWAPDOUBLE_CPY(psShape->padfY + i,
+ psSHP->pabyRec + nOffset + i * 16 + 8);
+#else
memcpy(psShape->padfX + i, psSHP->pabyRec + nOffset + i * 16, 8);
-
memcpy(psShape->padfY + i, psSHP->pabyRec + nOffset + i * 16 + 8,
8);
-
- if (bBigEndian)
- SwapWord(8, psShape->padfX + i);
- if (bBigEndian)
- SwapWord(8, psShape->padfY + i);
+#endif
}
nOffset += 16 * nPoints;
psShape->nSHPType == SHPT_ARCZ ||
psShape->nSHPType == SHPT_MULTIPATCH)
{
- memcpy(&(psShape->dfZMin), psSHP->pabyRec + nOffset, 8);
- memcpy(&(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(&psShape->dfZMin, psSHP->pabyRec + nOffset);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfZMax, psSHP->pabyRec + nOffset + 8);
+#else
+ memcpy(&psShape->dfZMin, psSHP->pabyRec + nOffset, 8);
+ memcpy(&psShape->dfZMax, psSHP->pabyRec + nOffset + 8, 8);
- if (bBigEndian)
- SwapWord(8, &(psShape->dfZMin));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfZMax));
+#endif
for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfZ + i,
+ psSHP->pabyRec + nOffset + 16 + i * 8);
+#else
memcpy(psShape->padfZ + i,
psSHP->pabyRec + nOffset + 16 + i * 8, 8);
- if (bBigEndian)
- SwapWord(8, psShape->padfZ + i);
+#endif
}
nOffset += 16 + 8 * nPoints;
/* -------------------------------------------------------------------- */
if (nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8 * nPoints))
{
- memcpy(&(psShape->dfMMin), psSHP->pabyRec + nOffset, 8);
- memcpy(&(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8);
-
- if (bBigEndian)
- SwapWord(8, &(psShape->dfMMin));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfMMax));
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(&psShape->dfMMin, psSHP->pabyRec + nOffset);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfMMax, psSHP->pabyRec + nOffset + 8);
+#else
+ memcpy(&psShape->dfMMin, psSHP->pabyRec + nOffset, 8);
+ memcpy(&psShape->dfMMax, psSHP->pabyRec + nOffset + 8, 8);
+#endif
for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfM + i,
+ psSHP->pabyRec + nOffset + 16 + i * 8);
+#else
memcpy(psShape->padfM + i,
psSHP->pabyRec + nOffset + 16 + i * 8, 8);
- if (bBigEndian)
- SwapWord(8, psShape->padfM + i);
+#endif
}
psShape->bMeasureIsUsed = TRUE;
}
uint32_t nPoints;
memcpy(&nPoints, psSHP->pabyRec + 44, 4);
- if (bBigEndian)
- SwapWord(4, &nPoints);
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAP32(&nPoints);
+#endif
/* nPoints is unsigned */
if (/* nPoints < 0 || */ nPoints > 50 * 1000 * 1000)
for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfX + i,
+ psSHP->pabyRec + 48 + 16 * i);
+ SHP_SWAPDOUBLE_CPY(psShape->padfY + i,
+ psSHP->pabyRec + 48 + 16 * i + 8);
+#else
memcpy(psShape->padfX + i, psSHP->pabyRec + 48 + 16 * i, 8);
memcpy(psShape->padfY + i, psSHP->pabyRec + 48 + 16 * i + 8, 8);
-
- if (bBigEndian)
- SwapWord(8, psShape->padfX + i);
- if (bBigEndian)
- SwapWord(8, psShape->padfY + i);
+#endif
}
int nOffset = 48 + 16 * nPoints;
/* -------------------------------------------------------------------- */
/* Get the X/Y bounds. */
/* -------------------------------------------------------------------- */
- memcpy(&(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8);
- memcpy(&(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8);
- memcpy(&(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8);
- memcpy(&(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8);
-
- if (bBigEndian)
- SwapWord(8, &(psShape->dfXMin));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfYMin));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfXMax));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfYMax));
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(&psShape->dfXMin, psSHP->pabyRec + 8 + 4);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfYMin, psSHP->pabyRec + 8 + 12);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfXMax, psSHP->pabyRec + 8 + 20);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfYMax, psSHP->pabyRec + 8 + 28);
+#else
+ memcpy(&psShape->dfXMin, psSHP->pabyRec + 8 + 4, 8);
+ memcpy(&psShape->dfYMin, psSHP->pabyRec + 8 + 12, 8);
+ memcpy(&psShape->dfXMax, psSHP->pabyRec + 8 + 20, 8);
+ memcpy(&psShape->dfYMax, psSHP->pabyRec + 8 + 28, 8);
+#endif
/* -------------------------------------------------------------------- */
/* If we have a Z coordinate, collect that now. */
/* -------------------------------------------------------------------- */
if (psShape->nSHPType == SHPT_MULTIPOINTZ)
{
- memcpy(&(psShape->dfZMin), psSHP->pabyRec + nOffset, 8);
- memcpy(&(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8);
-
- if (bBigEndian)
- SwapWord(8, &(psShape->dfZMin));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfZMax));
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(&psShape->dfZMin, psSHP->pabyRec + nOffset);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfZMax, psSHP->pabyRec + nOffset + 8);
+#else
+ memcpy(&psShape->dfZMin, psSHP->pabyRec + nOffset, 8);
+ memcpy(&psShape->dfZMax, psSHP->pabyRec + nOffset + 8, 8);
+#endif
for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfZ + i,
+ psSHP->pabyRec + nOffset + 16 + i * 8);
+#else
memcpy(psShape->padfZ + i,
psSHP->pabyRec + nOffset + 16 + i * 8, 8);
- if (bBigEndian)
- SwapWord(8, psShape->padfZ + i);
+#endif
}
nOffset += 16 + 8 * nPoints;
/* -------------------------------------------------------------------- */
if (nEntitySize >= STATIC_CAST(int, nOffset + 16 + 8 * nPoints))
{
- memcpy(&(psShape->dfMMin), psSHP->pabyRec + nOffset, 8);
- memcpy(&(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8);
-
- if (bBigEndian)
- SwapWord(8, &(psShape->dfMMin));
- if (bBigEndian)
- SwapWord(8, &(psShape->dfMMax));
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(&psShape->dfMMin, psSHP->pabyRec + nOffset);
+ SHP_SWAPDOUBLE_CPY(&psShape->dfMMax, psSHP->pabyRec + nOffset + 8);
+#else
+ memcpy(&psShape->dfMMin, psSHP->pabyRec + nOffset, 8);
+ memcpy(&psShape->dfMMax, psSHP->pabyRec + nOffset + 8, 8);
+#endif
for (int i = 0; STATIC_CAST(uint32_t, i) < nPoints; i++)
{
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfM + i,
+ psSHP->pabyRec + nOffset + 16 + i * 8);
+#else
memcpy(psShape->padfM + i,
psSHP->pabyRec + nOffset + 16 + i * 8, 8);
- if (bBigEndian)
- SwapWord(8, psShape->padfM + i);
+#endif
}
psShape->bMeasureIsUsed = TRUE;
}
SHPDestroyObject(psShape);
return SHPLIB_NULLPTR;
}
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfX, psSHP->pabyRec + 12);
+ SHP_SWAPDOUBLE_CPY(psShape->padfY, psSHP->pabyRec + 20);
+#else
memcpy(psShape->padfX, psSHP->pabyRec + 12, 8);
memcpy(psShape->padfY, psSHP->pabyRec + 20, 8);
-
- if (bBigEndian)
- SwapWord(8, psShape->padfX);
- if (bBigEndian)
- SwapWord(8, psShape->padfY);
+#endif
int nOffset = 20 + 8;
/* -------------------------------------------------------------------- */
if (psShape->nSHPType == SHPT_POINTZ)
{
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfZ, psSHP->pabyRec + nOffset);
+#else
memcpy(psShape->padfZ, psSHP->pabyRec + nOffset, 8);
-
- if (bBigEndian)
- SwapWord(8, psShape->padfZ);
+#endif
nOffset += 8;
}
/* -------------------------------------------------------------------- */
if (nEntitySize >= nOffset + 8)
{
+#if defined(SHP_BIG_ENDIAN)
+ SHP_SWAPDOUBLE_CPY(psShape->padfM, psSHP->pabyRec + nOffset);
+#else
memcpy(psShape->padfM, psSHP->pabyRec + nOffset, 8);
-
- if (bBigEndian)
- SwapWord(8, psShape->padfM);
+#endif
psShape->bMeasureIsUsed = TRUE;
}
/* specification. */
/************************************************************************/
-int SHPAPI_CALL SHPRewindObject(CPL_UNUSED SHPHandle hSHP, SHPObject *psObject)
+int SHPAPI_CALL SHPRewindObject(const SHPHandle hSHP, SHPObject *psObject)
{
+ (void)hSHP;
/* -------------------------------------------------------------------- */
/* Do nothing if this is not a polygon object. */
/* -------------------------------------------------------------------- */